package cn.itcast.nems.journal.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.itcast.nems.base.dto.ClazzDTO;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.constant.DiscountTypeEnum;
import cn.itcast.nems.common.constant.PaymentTypeEum;
import cn.itcast.nems.common.util.NumberUtil;
import cn.itcast.nems.discounts.dao.entiry.EmsDiscounts;
import cn.itcast.nems.journal.dto.JournalRenewalDTO;
import cn.itcast.nems.journal.dto.JournalRenewalLineDTO;
import cn.itcast.nems.journal.dto.JournalRenewalLineDiscountDTO;
import cn.itcast.nems.journal.enumeration.JournalStateEnum;
import cn.itcast.nems.manager.util.CustomBeanUtil;
import cn.itcast.nems.oldems.dto.CirculationWay;
import cn.itcast.nems.oldems.dto.StudentJoinClassInfo;
import cn.itcast.nems.oldems.dto.StudentRecordCirculation;
import cn.itcast.nems.order.dto.JournalDiscountApiResDTO;
import cn.itcast.nems.studentrecord.constant.DiscountScopeTypeEnum;
import cn.itcast.nems.studentrecord.constant.OrderSourceEnum;
import cn.itcast.nems.studentrecord.dao.condition.ApprovalType;
import cn.itcast.nems.studentrecord.dao.dataobject.JournalRenewalDO;
import cn.itcast.nems.studentrecord.dao.dataobject.JournalRenewalLineDiscountDO;
import cn.itcast.nems.studentrecord.dao.entity.JournalRenewal;
import cn.itcast.nems.studentrecord.dao.entity.JournalRenewalLineDiscount;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import com.alibaba.fastjson.JSON;
import lombok.NonNull;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

public class JournalRenewalUtil {
    private  final static Logger log = LoggerFactory.getLogger(JournalRenewalUtil.class) ;
    private JournalRenewalUtil() {}
    /**
     * <p>
     * 生成升级凭单头实体
     * </p>
     *
     * @param renewalDTO                                页面升级凭单参数
     * @author zhouwei
     * @since 2023/12/8 2:14 PM
     **/
    public static JournalRenewal wrapJournalRenewal(JournalRenewalDTO renewalDTO , String id) {
        JournalRenewal journalRenewal = CustomBeanUtil.copyProperties(renewalDTO, new JournalRenewal());
        journalRenewal.setTargetClazzPrice(Objects.nonNull(renewalDTO.getTargetClazzPrice()) ?
                renewalDTO.getTargetClazzPrice().multiply(BigDecimal.valueOf(100)).intValue() : null);
        journalRenewal.setId(id);
        journalRenewal.setRenewalQuantity(0);
        journalRenewal.setPaidQuantity(0);
        journalRenewal.setState(JournalStateEnum.DRAFT.name());
        journalRenewal.setBizDate(LocalDateTime.now());
        journalRenewal.setCreatedBy(AccountHolder.getRequiredAccount());
        journalRenewal.setRenewalQuantity(CollectionUtils.isNotEmpty(renewalDTO.getLineList()) ? renewalDTO.getLineList().size() : 0);
        return journalRenewal;
    }

    /**
     * <p>
     * 获取升级凭单工作流参数  
     * </p>
     *
     * @param recordIds                                 学籍ID
     * @param targetClazzId                             升级目标班级
     * @param specialFlag                               是否特殊审批
     * @author zhouwei
     * @since 2023/12/8 1:33 PM
     **/
    public static HashMap<String, Object> getVariables(
                                                        @NonNull List<String> recordIds ,
                                                        @NonNull Integer targetClazzId ,
                                                        Boolean specialFlag) {
        HashMap<String, Object> map = new HashMap<>();
        // 1、办理事项  handle_matters  （ "线下转线上博学谷" ， "转班"）
        map.put("handle_matters", OrderSourceEnum.RENEWAL.getCname());
        // 2、是否特殊审批 special_approval （"true"， "false"）
        map.put("special_approval", Objects.isNull(specialFlag) || !specialFlag ? "false": "true");
        log.info("【获取工作流参数】参数：{}" , JSON.toJSONString(map));
        return map ;
    }
    /**
     * <p>
     * 根据审批类型获取升级凭单分页查询条件
     * </p>
     *
     * @param journalIds                        审批单ID
     * @param renewalDO                                 升级凭单
     * @param approvalType                              审批类型
     * @author zhouwei
     * @since 2023/12/8 1:34 PM
     **/
    public static void invokeJournalRenewalDOByApprovalType (
                                                        List<String> journalIds ,
                                                        JournalRenewalDO renewalDO ,
                                                        ApprovalType approvalType ){
        if (approvalType == ApprovalType.MY_COMMIT) {
            renewalDO.setScopeOrCreatedBy(AccountHolder.getRequiredAccount());
        } else if (approvalType == ApprovalType.WAIT_APPROVAL) {
            // 待我审核、审核中
            renewalDO.setScopeOrIdIn(journalIds);
            renewalDO.setNotDraft(true);
        }  else if (approvalType == ApprovalType.APPROVED) {
            // 我审核过的
            renewalDO.setScopeOrIdIn(journalIds);
            renewalDO.setScopeOrIdInCreatedBy(AccountHolder.getRequiredAccount());
            renewalDO.setNotDraft(true);
        } else if (approvalType == ApprovalType.ALL) {
            renewalDO.setNotDraft(true);
        }
    }
    
    /**
     * <p>
     * 生成升级凭单行优惠实体
     * </p>
     *
     * @param renewalId                                 升级凭单头ID
     * @param renewalLineId                             升级凭单行ID
     * @param lineDiscountDTO                           页面行优惠DTO
     * @param targetClazzPrice                          目标班级执行价格
     * @param lineDiscountAmount                        该学员凭单头优惠+ 行优惠合计
     * @param index                                     对应排序号
     * @author zhouwei
     * @since 2023/12/8 1:56 PM
     **/
    public static  JournalRenewalLineDiscount wrapJournalRenewalLineDiscount(
                                                        String renewalId ,
                                                        String renewalLineId,
                                                        JournalRenewalLineDiscountDTO lineDiscountDTO ,
                                                        BigDecimal targetClazzPrice,
                                                        int lineDiscountAmount ,
                                                        int index) {
        int price = NumberUtil.convertToCent(targetClazzPrice) ;
        JournalRenewalLineDiscount lineDiscount = new JournalRenewalLineDiscount();
        int discountAmount = Objects.nonNull(lineDiscountDTO.getDiscountAmount()) ? lineDiscountDTO.getDiscountAmount().multiply(BigDecimal.valueOf(100)).intValue() : 0;
        if (DiscountTypeEnum.DISCOUNT.name().equalsIgnoreCase(lineDiscountDTO.getDiscountType())) {
            discountAmount = targetClazzPrice.multiply(lineDiscountDTO.getDiscountRate()).multiply(BigDecimal.valueOf(100)).intValue();
        }
        lineDiscount.setDiscountType(lineDiscountDTO.getDiscountType());
        lineDiscount.setDiscountScopeType(lineDiscountDTO.getDiscountScopeType());
        lineDiscount.setJournalDiscountLineId(lineDiscountDTO.getJournalDiscountLineId());
        lineDiscount.setDiscountId(lineDiscountDTO.getDiscountId());
        lineDiscount.setDiscountAmount(Math.min(discountAmount, (price - lineDiscountAmount)));
        lineDiscount.setDiscountName(lineDiscountDTO.getDiscountName());
        lineDiscount.setJournalRenewalId(renewalId);
        lineDiscount.setJournalRenewalLineId(renewalLineId);
        lineDiscount.setSort(index + 1);
        lineDiscount.setDescription(lineDiscountDTO.getDiscountName());
        return  lineDiscount ;
    }

    /**
     * <p>
     * 生成升级凭单行优惠实体
     * </p>
     *
     * @param lineDiscountDTO 升级凭单行参数
     * @param apiResDTO       个人优惠单DTO
     * @param discounts       普通优惠实体
     * @author zhouwei
     * @since 2023/12/8 1:56 PM
     **/
    public static void transferJournalRenewalLineDiscountDTO(JournalRenewalLineDiscountDTO lineDiscountDTO,
                                                             JournalDiscountApiResDTO apiResDTO, EmsDiscounts discounts) {
        if (DiscountScopeTypeEnum.PERSONAL.name().equalsIgnoreCase(lineDiscountDTO.getDiscountScopeType())) {
            lineDiscountDTO.setDiscountName(apiResDTO.getDiscountName());
            lineDiscountDTO.setDiscountType(apiResDTO.getDiscountType());
            if (DiscountTypeEnum.DISCOUNT.name().equalsIgnoreCase(apiResDTO.getDiscountType())) {
                lineDiscountDTO.setDiscountRate(apiResDTO.getDiscountValue());
            } else {
                lineDiscountDTO.setDiscountAmount(apiResDTO.getDiscountValue());
            }
        } else {
            lineDiscountDTO.setDiscountName(discounts.getDiscountsName());
            String discountType = Objects.nonNull(discounts.getDiscountsStatus()) && discounts.getDiscountsStatus() == 1 ?
                    DiscountTypeEnum.DISCOUNT.name() : DiscountTypeEnum.CASH.name();
            lineDiscountDTO.setDiscountType(discountType);
            if (DiscountTypeEnum.DISCOUNT.name().equalsIgnoreCase(discountType)) {
                lineDiscountDTO.setDiscountRate(BigDecimal.valueOf(discounts.getDiscountsRate()));
            } else {
                lineDiscountDTO.setDiscountAmount(discounts.getDiscountsMoney());
            }
        }
    }

    /**
     * <p>
     * 合并凭单行中的普通优惠和个人优惠
     * </p>
     *
     * @param lineDTO                               页面参数
     * @author zhouwei
     * @since 2023/12/8 3:20 PM
     **/
    public static List<JournalRenewalLineDiscountDTO> getLineDiscountList(JournalRenewalLineDTO lineDTO){
        List<JournalRenewalLineDiscountDTO> discountList = new ArrayList<>();
        discountList.addAll(Objects.requireNonNullElse(lineDTO.getDiscountList(), new ArrayList<JournalRenewalLineDiscountDTO>())
                .stream().peek(item -> item.setDiscountScopeType(DiscountScopeTypeEnum.NORMAL.name())).toList());
        discountList.addAll(Objects.requireNonNullElse(lineDTO.getDiscountCouponList(), new ArrayList<JournalRenewalLineDiscountDTO>())
                .stream().peek(item -> item.setDiscountScopeType(DiscountScopeTypeEnum.PERSONAL.name())).toList());
        return  discountList ;
    }

    /**
     * <p>
     * 将升级凭单学籍信息同步至老EMS
     * </p>
     *
     * @param renewalDTO 凭单数据（包含：升级凭单头、头优惠列表、行数据）
     * @author zhouwei
     * @since 2024/3/19 9:19 AM
     **/
    public static List<StudentRecordCirculation> wrapCirculations(JournalRenewalDTO renewalDTO,
                                                                  List<Integer> discountIdsList,
                                                                  Map<String, StudentRecord> studentRecordMap,
                                                                  Map<String,List<JournalRenewalLineDiscountDO>> lineDiscountMap,
                                                                  ClazzDTO clazzDTO) {
        if (CollectionUtil.isEmpty(renewalDTO.getLineList())) {
            log.info("【审批完成】升级凭单行列表为空，无需同步学籍至老EMS");
            return null;
        }
        // EmployeeDTO employee = Objects.nonNull(renewalDTO.getEmployee()) ? renewalDTO.getEmployee() : new EmployeeDTO();
        // AccountInfo accountInfo = new AccountInfo(employee.getEmail(), employee.getName(), employee.getJobNumber(), null);
        return renewalDTO.getLineList()
                .stream()
                .map(item -> {
                            StudentRecord studentRecord = studentRecordMap.get(item.getOriginStudentRecordId());
                            List<JournalRenewalLineDiscountDO> renewalLineDiscountList = Objects.requireNonNullElse(lineDiscountMap.get(item.getId()), new ArrayList<JournalRenewalLineDiscountDO>());
                            List<Integer> discountIds = ListUtils.sum(discountIdsList, renewalLineDiscountList.stream().map(d -> Integer.valueOf(d.getDiscountId())).toList());
                            StudentJoinClassInfo origin = StudentJoinClassInfo
                                    .builder()
                                    .clazzId(item.getOriginClazzId())
                                    .inDate(Objects.isNull(studentRecord.getInDate()) ? null : studentRecord.getInDate().toLocalDate())
                                    .outDate(item.getOriginClazzOutDate())
                                    .paymentType(PaymentTypeEum.FIRSTPAYMENT)
                                    .serviceDays(0)
                                    .actualServiceDays(0)
                                    .price(studentRecord.getPrice())
                                    .build();
                            StudentJoinClassInfo target = StudentJoinClassInfo
                                    .builder()
                                    .clazzId(renewalDTO.getTargetClazzId())
                                    .inDate(item.getTargetClazzInDate())
                                    .outDate(null)
                                    .paymentType(PaymentTypeEum.FIRSTPAYMENT)
                                    .price(NumberUtil.convertToCent(item.getTargetClazzOriginalAmount()))
                                    .openClass(Objects.nonNull(clazzDTO.getStartDate()) &&  !item.getTargetClazzInDate().isBefore(clazzDTO.getStartDate()))
                                    .discountIds(discountIds)
                                    .build();
                            return StudentRecordCirculation
                                    .builder()
                                    .studentId(item.getStudentId())
                                    .originStudentJoinClassInfo(origin)
                                    .targetStudentJoinClassInfo(target)
                                    .circulationWay(CirculationWay.UPGRADE)
                                    .operator(AccountHolder.getRequiredAccountInfo())
                                    // .operator(new AccountInfo("lvning@itcast.cn", "吕宁", "93653", null))
                                    .build();
                        }
                ).toList();

    }

}
